[HVM] Save/restore: clean up the new hypercall interface
authorTim Deegan <Tim.Deegan@xensource.com>
Wed, 31 Jan 2007 17:22:00 +0000 (17:22 +0000)
committerTim Deegan <Tim.Deegan@xensource.com>
Wed, 31 Jan 2007 17:22:00 +0000 (17:22 +0000)
Pass a buffer and size through instead of fixed-size structure.

Signed-off-by: Zhai Edwin <edwin.zhai@intel.com>
Signed-off-by: Tim Deegan <Tim.Deegan@xensource.com>
tools/libxc/xc_domain.c
tools/libxc/xc_hvm_restore.c
tools/libxc/xc_hvm_save.c
tools/libxc/xenctrl.h
xen/arch/x86/domctl.c
xen/arch/x86/hvm/intercept.c
xen/include/asm-x86/hvm/domain.h
xen/include/asm-x86/hvm/support.h
xen/include/public/domctl.h

index 6b674502615b77be668c8607dc73a3fd50a288c5..e557f43f136dfb363eb21ca13145cd81575056b0 100644 (file)
@@ -241,45 +241,49 @@ int xc_domain_getinfolist(int xc_handle,
 /* get info from hvm guest for save */
 int xc_domain_hvm_getcontext(int xc_handle,
                              uint32_t domid,
-                             hvm_domain_context_t *hvm_ctxt)
+                             uint8_t *ctxt_buf,
+                             uint32_t size)
 {
-    int rc;
+    int ret;
     DECLARE_DOMCTL;
 
     domctl.cmd = XEN_DOMCTL_gethvmcontext;
     domctl.domain = (domid_t)domid;
-    set_xen_guest_handle(domctl.u.hvmcontext.ctxt, hvm_ctxt);
+    domctl.u.hvmcontext.size = size;
+    set_xen_guest_handle(domctl.u.hvmcontext.buffer, ctxt_buf);
 
-    if ( (rc = mlock(hvm_ctxt, sizeof(*hvm_ctxt))) != 0 )
-        return rc;
+    if ( (ret = lock_pages(ctxt_buf, size)) != 0 )
+        return ret;
 
-    rc = do_domctl(xc_handle, &domctl);
+    ret = do_domctl(xc_handle, &domctl);
 
-    safe_munlock(hvm_ctxt, sizeof(*hvm_ctxt));
+    unlock_pages(ctxt_buf, size);
 
-    return rc;
+    return (ret < 0 ? -1 : domctl.u.hvmcontext.size);
 }
 
 /* set info to hvm guest for restore */
 int xc_domain_hvm_setcontext(int xc_handle,
                              uint32_t domid,
-                             hvm_domain_context_t *hvm_ctxt)
+                             uint8_t *ctxt_buf,
+                             uint32_t size)
 {
-    int rc;
+    int ret;
     DECLARE_DOMCTL;
 
     domctl.cmd = XEN_DOMCTL_sethvmcontext;
     domctl.domain = domid;
-    set_xen_guest_handle(domctl.u.hvmcontext.ctxt, hvm_ctxt);
+    domctl.u.hvmcontext.size = size;
+    set_xen_guest_handle(domctl.u.hvmcontext.buffer, ctxt_buf);
 
-    if ( (rc = mlock(hvm_ctxt, sizeof(*hvm_ctxt))) != 0 )
-        return rc;
+    if ( (ret = lock_pages(ctxt_buf, size)) != 0 )
+        return ret;
 
-    rc = do_domctl(xc_handle, &domctl);
+    ret = do_domctl(xc_handle, &domctl);
 
-    safe_munlock(hvm_ctxt, sizeof(*hvm_ctxt));
+    unlock_pages(ctxt_buf, size);
 
-    return rc;
+    return ret;
 }
 
 int xc_vcpu_getcontext(int xc_handle,
index b2b9999feae1f88254af3333d239bf842faae828..6622b49f79cfbcbdfd56acda9cbbc98699fd2a51 100644 (file)
@@ -87,7 +87,7 @@ int xc_hvm_restore(int xc_handle, int io_fd,
     xc_dominfo_t info;
     unsigned int rc = 1, n, i;
     uint32_t rec_len, nr_vcpus;
-    hvm_domain_context_t hvm_ctxt;
+    uint8_t *hvm_buf = NULL;
     unsigned long long v_end, memsize;
     unsigned long shared_page_nr;
 
@@ -128,8 +128,7 @@ int xc_hvm_restore(int xc_handle, int io_fd,
     }
 
 
-    p2m        = malloc(max_pfn * sizeof(xen_pfn_t));
-
+    p2m = malloc(max_pfn * sizeof(xen_pfn_t));
     if (p2m == NULL) {
         ERROR("memory alloc failed");
         errno = ENOMEM;
@@ -297,18 +296,21 @@ int xc_hvm_restore(int xc_handle, int io_fd,
         ERROR("error read hvm context size!\n");
         goto out;
     }
-    if (rec_len != sizeof(hvm_ctxt)) {
-        ERROR("hvm context size dismatch!\n");
+
+    hvm_buf = malloc(rec_len);
+    if (hvm_buf == NULL) {
+        ERROR("memory alloc for hvm context buffer failed");
+        errno = ENOMEM;
         goto out;
     }
 
-    if (!read_exact(io_fd, &hvm_ctxt, sizeof(hvm_ctxt))) {
-        ERROR("error read hvm context!\n");
+    if (!read_exact(io_fd, hvm_buf, rec_len)) {
+        ERROR("error read hvm buffer!\n");
         goto out;
     }
 
-    if (( rc = xc_domain_hvm_setcontext(xc_handle, dom, &hvm_ctxt))) {
-        ERROR("error set hvm context!\n");
+    if (( rc = xc_domain_hvm_setcontext(xc_handle, dom, hvm_buf, rec_len))) {
+        ERROR("error set hvm buffer!\n");
         goto out;
     }
 
@@ -361,6 +363,7 @@ int xc_hvm_restore(int xc_handle, int io_fd,
     if ( (rc != 0) && (dom != 0) )
         xc_domain_destroy(xc_handle, dom);
     free(p2m);
+    free(hvm_buf);
 
     DPRINTF("Restore exit with rc=%d\n", rc);
 
index 3d08a509d9929985d2da36f99a6784abdce6a3b7..d9cca58d07347a5ef660ab802c60cfbfd5717e5a 100644 (file)
 #include "xg_private.h"
 #include "xg_save_restore.h"
 
+/*
+ * Size of a buffer big enough to take the HVM state of a domain.
+ * Ought to calculate this a bit more carefully, or maybe ask Xen.
+ */
+#define HVM_CTXT_SIZE 8192
+
 /*
 ** Default values for important tuning parameters. Can override by passing
 ** non-zero replacement values to xc_hvm_save().
@@ -279,8 +285,8 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
     unsigned long *pfn_type = NULL;
     unsigned long *pfn_batch = NULL;
 
-    /* A copy of hvm domain context */
-    hvm_domain_context_t hvm_ctxt;
+    /* A copy of hvm domain context buffer*/
+    uint8_t *hvm_buf = NULL;
 
     /* Live mapping of shared info structure */
     shared_info_t *live_shinfo = NULL;
@@ -423,8 +429,12 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
     to_send = malloc(BITMAP_SIZE);
     to_skip = malloc(BITMAP_SIZE);
 
-    if (!to_send ||!to_skip) {
-        ERROR("Couldn't allocate to_send array");
+    page_array = (unsigned long *) malloc( sizeof(unsigned long) * max_pfn);
+
+    hvm_buf = malloc(HVM_CTXT_SIZE);
+
+    if (!to_send ||!to_skip ||!page_array ||!hvm_buf ) {
+        ERROR("Couldn't allocate memory");
         goto out;
     }
 
@@ -444,11 +454,6 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
     analysis_phase(xc_handle, dom, max_pfn, to_skip, 0);
 
     /* get all the HVM domain pfns */
-    if ( (page_array = (unsigned long *) malloc (sizeof(unsigned long) * max_pfn)) == NULL) {
-        ERROR("HVM:malloc fail!\n");
-        goto out;
-    }
-
     for ( i = 0; i < max_pfn; i++)
         page_array[i] = i;
 
@@ -655,24 +660,18 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
         goto out;
     }
 
-    /* save hvm hypervisor state including pic/pit/shpage */
-    if (mlock(&hvm_ctxt, sizeof(hvm_ctxt))) {
-        ERROR("Unable to mlock ctxt");
-        return 1;
-    }
-
-    if (xc_domain_hvm_getcontext(xc_handle, dom, &hvm_ctxt)){
-        ERROR("HVM:Could not get hvm context");
+    if ( (rec_size = xc_domain_hvm_getcontext(xc_handle, dom, hvm_buf, 
+                                              HVM_CTXT_SIZE)) == -1) {
+        ERROR("HVM:Could not get hvm buffer");
         goto out;
     }
 
-    rec_size = sizeof(hvm_ctxt);
     if (!write_exact(io_fd, &rec_size, sizeof(uint32_t))) {
-        ERROR("error write hvm ctxt size");
+        ERROR("error write hvm buffer size");
         goto out;
     }
 
-    if ( !write_exact(io_fd, &hvm_ctxt, sizeof(hvm_ctxt)) ) {
+    if ( !write_exact(io_fd, hvm_buf, rec_size) ) {
         ERROR("write HVM info failed!\n");
     }
 
@@ -722,6 +721,7 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
         }
     }
 
+    free(hvm_buf);
     free(page_array);
 
     free(pfn_type);
index 26cd638db5216ce3f7e171ddcad3b24b64cef5f1..14704e2e92435d9b6b873712bb11bb8a16c92efe 100644 (file)
@@ -328,13 +328,15 @@ int xc_domain_getinfolist(int xc_handle,
  * This function returns information about the context of a hvm domain
  * @parm xc_handle a handle to an open hypervisor interface
  * @parm domid the domain to get information from
- * @parm hvm_ctxt a pointer to a structure to store the execution context of the
- *            hvm domain
+ * @parm ctxt_buf a pointer to a structure to store the execution context of
+ *            the hvm domain
+ * @parm size the size of ctxt_buf in bytes
  * @return 0 on success, -1 on failure
  */
 int xc_domain_hvm_getcontext(int xc_handle,
                              uint32_t domid,
-                             hvm_domain_context_t *hvm_ctxt);
+                             uint8_t *ctxt_buf,
+                             uint32_t size);
 
 /**
  * This function will set the context for hvm domain
@@ -342,11 +344,13 @@ int xc_domain_hvm_getcontext(int xc_handle,
  * @parm xc_handle a handle to an open hypervisor interface
  * @parm domid the domain to set the hvm domain context for
  * @parm hvm_ctxt pointer to the the hvm context with the values to set
+ * @parm size the size of hvm_ctxt in bytes
  * @return 0 on success, -1 on failure
  */
 int xc_domain_hvm_setcontext(int xc_handle,
                              uint32_t domid,
-                             hvm_domain_context_t *hvm_ctxt);
+                             uint8_t *hvm_ctxt,
+                             uint32_t size);
 
 /**
  * This function returns information about the execution context of a
index db18c7cecfef6a3a237199a4b64586c6c86cf0ac..d73ae65bd50ca9bed1080528adcdaa520c09cf64 100644 (file)
@@ -288,71 +288,73 @@ long arch_do_domctl(
 
     case XEN_DOMCTL_sethvmcontext:
     { 
-        struct hvm_domain_context *c;
+        struct hvm_domain_context c;
         struct domain             *d;
 
+        c.cur = 0;
+        c.size = domctl->u.hvmcontext.size;
+        c.data = NULL;
+        
         ret = -ESRCH;
         if ( (d = get_domain_by_id(domctl->domain)) == NULL )
             break;
 
-        ret = -ENOMEM;
-        if ( (c = xmalloc(struct hvm_domain_context)) == NULL )
-            goto sethvmcontext_out;
-        
-        ret = -EFAULT;
-        if ( copy_from_guest(c, domctl->u.hvmcontext.ctxt, 1) != 0 )
-            goto sethvmcontext_out;
-        c->size = sizeof (c->data);
-        c->cur = 0;
-
         ret = -EINVAL;
         if ( !is_hvm_domain(d) ) 
             goto sethvmcontext_out;
 
-        ret = hvm_load(d, c);
+        ret = -ENOMEM;
+        if ( (c.data = xmalloc_bytes(c.size)) == NULL )
+            goto sethvmcontext_out;
+
+        ret = -EFAULT;
+        if ( copy_from_guest(c.data, domctl->u.hvmcontext.buffer, c.size) != 0)
+            goto sethvmcontext_out;
 
-        xfree(c);
+        ret = hvm_load(d, &c);
 
     sethvmcontext_out:
-        put_domain(d);
+        if ( c.data != NULL )
+            xfree(c.data);
 
+        put_domain(d);
     }
     break;
 
     case XEN_DOMCTL_gethvmcontext:
     { 
-        struct hvm_domain_context *c;
+        struct hvm_domain_context c;
         struct domain             *d;
 
+        c.cur = 0;
+        c.size = domctl->u.hvmcontext.size;
+        c.data = NULL;
+
         ret = -ESRCH;
         if ( (d = get_domain_by_id(domctl->domain)) == NULL )
             break;
 
-        ret = -ENOMEM;
-        if ( (c = xmalloc(struct hvm_domain_context)) == NULL )
-            goto gethvmcontext_out;
-        memset(c, 0, sizeof(*c));
-        c->size = sizeof (c->data);
-        
-        ret = -ENODATA;
+        ret = -EINVAL;
         if ( !is_hvm_domain(d) ) 
             goto gethvmcontext_out;
-        
-        ret = 0;
-        if (hvm_save(d, c) != 0)
-            ret = -EFAULT;
 
-        if ( copy_to_guest(domctl->u.hvmcontext.ctxt, c, 1) )
-            ret = -EFAULT;
+        ret = -ENOMEM;
+        if ( (c.data = xmalloc_bytes(c.size)) == NULL )
+            goto gethvmcontext_out;
 
-        xfree(c);
+        ret = hvm_save(d, &c);
+
+        if ( copy_to_guest(domctl->u.hvmcontext.buffer, c.data, c.size) != 0 )
+            ret = -EFAULT;
 
         if ( copy_to_guest(u_domctl, domctl, 1) )
             ret = -EFAULT;
 
     gethvmcontext_out:
-        put_domain(d);
+        if ( c.data != NULL )
+            xfree(c.data);
 
+        put_domain(d);
     }
     break;
 
index 802f67e0771675569ef8d6f7af1d8174264acf72..f130a252ab669800663bc124de6c57b493bfb001 100644 (file)
@@ -205,7 +205,7 @@ int hvm_save(struct domain *d, hvm_domain_context_t *h)
     if ( hvm_save_entry(HEADER, 0, h, &hdr) != 0 )
     {
         gdprintk(XENLOG_ERR, "HVM save: failed to write header\n");
-        return -1;
+        return -EFAULT;
     } 
 
     /* Save all available kinds of state */
@@ -219,7 +219,7 @@ int hvm_save(struct domain *d, hvm_domain_context_t *h)
             {
                 gdprintk(XENLOG_ERR, 
                          "HVM save: failed to save type %"PRIu16"\n", i);
-                return -1;
+                return -EFAULT;
             } 
         }
     }
@@ -229,7 +229,7 @@ int hvm_save(struct domain *d, hvm_domain_context_t *h)
     {
         /* Run out of data */
         gdprintk(XENLOG_ERR, "HVM save: no room for end marker.\n");
-        return -1;
+        return -EFAULT;
     }
 
     /* Save macros should not have let us overrun */
index f0b818462b98ddea4d0789227ef994219c84839b..8c5c5f274827971fced43e8612ef1f98ab6addd6 100644 (file)
@@ -49,8 +49,6 @@ struct hvm_domain {
     spinlock_t             pbuf_lock;
 
     uint64_t               params[HVM_NR_PARAMS];
-
-    struct hvm_domain_context *hvm_ctxt;
 };
 
 #endif /* __ASM_X86_HVM_DOMAIN_H__ */
index 066fba87d07f51b935e279d19bdf16caab8c9360..6d57140faea8fc4d539385e6c6163c4f507f06ae 100644 (file)
@@ -123,6 +123,13 @@ extern unsigned int opt_hvm_debug_level;
  * Save/restore support 
  */
 
+/* Marshalling and unmarshalling uses a buffer with size and cursor. */
+typedef struct hvm_domain_context {
+    uint32_t cur;
+    uint32_t size;
+    uint8_t *data;
+} hvm_domain_context_t;
+
 /* Marshalling an entry: check space and fill in the header */
 static inline int _hvm_init_entry(struct hvm_domain_context *h,
                                   uint16_t tc, uint16_t inst, uint32_t len)
index ad255f24d1f6355f009fe0782ce49f254cdb99b1..93f44f3ba58a208b173dab9654dc1b55b2169dd1 100644 (file)
@@ -386,18 +386,11 @@ struct xen_domctl_settimeoffset {
 typedef struct xen_domctl_settimeoffset xen_domctl_settimeoffset_t;
 DEFINE_XEN_GUEST_HANDLE(xen_domctl_settimeoffset_t);
  
-#define HVM_CTXT_SIZE        8192
-typedef struct hvm_domain_context {
-    uint32_t cur;
-    uint32_t size;
-    uint8_t data[HVM_CTXT_SIZE];
-} hvm_domain_context_t;
-DEFINE_XEN_GUEST_HANDLE(hvm_domain_context_t);
-
 #define XEN_DOMCTL_gethvmcontext   33
 #define XEN_DOMCTL_sethvmcontext   34
 typedef struct xen_domctl_hvmcontext {
-    XEN_GUEST_HANDLE_64(hvm_domain_context_t) ctxt;  /* IN/OUT */
+    uint32_t size; /* IN/OUT: size of buffer / bytes filled */
+    XEN_GUEST_HANDLE(uint8_t) buffer; /* IN/OUT */
 } xen_domctl_hvmcontext_t;
 DEFINE_XEN_GUEST_HANDLE(xen_domctl_hvmcontext_t);